
class User < ActiveRecord::Base  
  
  has_one :user_logo, :order => 'created_at desc'
  has_many :user_tool_settings
  has_many :sms
  has_many :follow_hot_post_settings
  belongs_to :fetion
  
  validates_presence_of :nick_name
  validates_uniqueness_of :nick_name, :case_sensitive => false
  validates_format_of :email, :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i
  validates_uniqueness_of :email,:case_sensitive => false
  validates_confirmation_of :encrypted_password
  validates_uniqueness_of :mobile, :on => :update, :allow_blank => true
  validates_presence_of :encrypted_password
  
  def current?
    id == User.current_user_id
  end
  # :robot_mobile & :mobile & :verify_code
  def bind_fetion_by(args = {})
    lite_fetion = LiteFetion.new(
        :id => args[:robot_mobile]
    ).get(
      :add_buddy,
      :distMobile => args[:mobile],
      :localName => nick_name,
      :verifyCode => args[:verify_code]
    )
    fetion_robot = Fetion.find_by_mobile(args[:robot_mobile])
    logger.debug "====================================================="
    logger.debug "====== #{args[:robot_mobile]} 加 #{args[:mobile]} 为好友的结果是 #{lite_fetion['result']}"
    logger.debug "====== #{lite_fetion}"
    logger.debug "====================================================="
    if lite_fetion['result'] == 'SUCCESS'
      lite_fetion_status!('wait') 
    end
    if lite_fetion['result'] == 'BUDDY_EXISTS'
      lite_fetion_status!('success')    
    end
    if lite_fetion['result'] == 'SUCCESS' or lite_fetion['result'] == 'BUDDY_EXISTS'
      bind_if_present! :mobile => args[:mobile],
        :fetion_id => fetion_robot.id,
        :fetion_version => 'lite',
        :fetion_sid => lite_fetion['s_id'],
        :fetion_user_id => lite_fetion['user_id'],
        :binded_at => Time.now
      fetion.reset_users_count!
    end
    lite_fetion
  end
  
  def try_to_send_sm_by_lite_fetion(content)
    LiteFetion.new(:id => fetion.mobile).get(
      :send_sm,
      :distMobile => mobile,
      :fetionUserId => (fetion_user_id.blank? ? '0' : fetion_user_id),
      :content => content
    ) 
  end
  
  def asyn_send_sm!(content)
    Sm.create! :user_id => id,
      :content => content
    add_sms_count!
  end
  
  def send_sm_by_lite_fetion(content)
    if not Rails.env.test?
      if fetion_version.lite? and mobile.present? and fetion.present? and lite_fetion_status.success?
        if not Rails.env.test?
          @result = try_to_send_sm_by_lite_fetion(content)
          raise @result['send_message_result'] if @result['send_message_result'] != 'SUCCESS'
        end
      else
        raise "cant send sm by lite_fetion : fetion_version.lite? is #{fetion_version.lite?}; mobile.present? is #{mobile.present?}; fetion.present? is #{fetion.present?}; lite_fetion_status.success? is #{lite_fetion_status.success?} "
      end
    end
  end
  
  def send_sm_by_lite_fetion!(content)
    send_sm_by_lite_fetion content
    UserSmsEmailsDailyStat.today_stat_by_mobile(mobile).add_sms_count!() if mobile?
  end
  
  def call_name
    current? ? '我' : nick_name
  end
  
  def check_password(other_password)
    other_password.present? ? Base64.encode64(other_password).chop == encrypted_password : false
  end
  
  # 会导致重复mobile
  def bind!(args = {})
    self.mobile = args[:mobile]
    self.fetion = args[:fetion]
    save false
  end
  
  # 会导致重复mobile
  def bind_if_present!(args = {})
    args.keys.each do |key|
      logger.debug "bind #{key} => #{self[key]}"
      if(key == 'fetion_sid' and args[key] != '0' or key != 'fetion_sid' and args[key].present? or key == 'fetion_user_id' and args[key] != '0' or key != 'fetion_user_id' and args[key].present?
      )
        self[key] = args[key] 
      end
    end
    save false
  end
  
  def logo
    user_logo
  end
  
  def zhui_settings
    FollowHotPostSetting.find_all_by_user_id_and_status(id,'zhui')
  end
  
  def last_sms(options = { :limit => 10 })
    Sm.find_all_by_user_id id, :order => 'created_at desc', :limit => options[:limit]
  end
  
  def all_settings_by_tool_type_id(tool_type_id)
    if tool_type_id.blank?
      user_tool_settings
    else
      UserToolSetting.all :conditions => [
        'user_id = ? and tools.tool_type_id = ? ',
        id,
        tool_type_id
      ],
        :include => :tool
    end
  end
  
  # 安全key存储在cookies
  def security_key_in_cookies
    Digest::SHA1.hexdigest(id.to_s + pk)
  end

  def check_security_key_in_cookies(sk)
    security_key_in_cookies == sk
  end
  
  # resort user_tool_settings of each column
  def resort_user_tool_settings(args ={})
    args[:settings].each_with_index do |setting,index|
      setting.update_attributes(
        :column => args[:column],
        :position => index
      ) if setting.user_id == id
    end if args[:settings].present?
  end

  def send_password_email!
     UserMailer.deliver_send_password self
  end

  def enjoy_default_tools!
    city = City.find_by_ip(Thread.current[:remote_ip]) || City.first
    UserToolSetting::WeatherForecast.create!(
      :user_id => id,
      :city_id => city.id,
      :area_id => city.city_area.id,
      :tool_id => Tool.find_by_code('weather_forecast').id,
      :column => 3
    )
    #UserToolSetting::WebFetion.create!(
    #  :user_id => id,
    #  :tool_id => Tool.find_by_code('web_fetion').id,
    #  :column => 2
    #)
    UserToolSetting::SiteHealth.create!(
      :name => '海南在线',
      :site_url => 'http://hainan.net',
      :content_keyword => 'hainan',
      :report_hour => 17,
      :user_id => id,
      :allow_sms => 'no',
      :tool_id => Tool.find_by_code('site_health').id,
      :column => 2
    )
    UserToolSetting::FavoriteSearch.create!(
      :user_id => id,
      :tool_id => Tool.find_by_code('favorite_search').id,
      :column => 1
    )
    
    UserToolSetting::ZhuiTianYa.create!(
      :user_id => id,
      :tool_id => Tool.find_by_code('zhui_tian_ya').id,
      :column => 1
    )

    UserToolSetting::NumberLocation.create!(
      :user_id => id,
      :tool_id => Tool.find_by_code('number_location').id,
      :column => 2
    )
    
    UserToolSetting::OpenApis.create!(
      :user_id => id,
      :tool_id => Tool.find_by_code('open_apis').id,
      :column => 2
    )
  end
  
  def before_create
    self.pk = ActiveSupport::SecureRandom.hex(64)
  end
  
  def before_save
    encode_password! if encrypted_password_changed?
    encode_fetion_password! if encrypted_fetion_password_changed?
  end
  
  def after_create
    Feed::MoneyJoin.create! :user_id => id
    Feed::MoneyIntroduceToJoin.create!( :user_id => introducer_id,
      :introducedor_id => id
    ) if introducer_id.present?
  end
  
  def self.all_binded_mobile
    find_all_by_fetion_version_and_lite_fetion_status('lite','success',:order => 'rand()')
  end
  
  def self.newers(limit = 21)
    all :order => 'created_at desc', :limit => limit
  end
  
  def self.logins(limit = 21)
    all :order => 'login_at desc', :limit => limit
  end
  
  # 当前登录的user
  def self.current_user
    Thread.current[:current_user_id] ? find(Thread.current[:current_user_id]) : nil
  end

  def self.current_user_id
    Thread.current[:current_user_id]
  end
  
  # 介绍人
  def introducer_id
    Thread.current[:introducer_id]
  end
  
  def introducer
    Thread.current[:introducer_id] ? User.find(Thread.current[:introducer_id]) : nil
  end
  
  def self.find_by_nick_name_or_email_or_mobile(nick_name_or_email_or_mobile)
    first :conditions => [
      'nick_name = ? or email = ? or mobile = ?',
      nick_name_or_email_or_mobile,
      nick_name_or_email_or_mobile,
      nick_name_or_email_or_mobile
    ]
  end
  
  def self.find_by_nick_name_or_email_or_mobile_and_encrypted_password(nick_name_or_email_or_mobile,encrypted_password)
    first :conditions => [
      '(nick_name = ? or email = ? or mobile = ?) and encrypted_password = ?',
      nick_name_or_email_or_mobile,
      nick_name_or_email_or_mobile,
      nick_name_or_email_or_mobile,
      encrypted_password
    ]
  end
  
  def self.authenticate(nick_name_or_email_or_mobile, password)
    find_by_nick_name_or_email_or_mobile_and_encrypted_password(nick_name_or_email_or_mobile,
      Base64.encode64(password).chop)
  end
  
  def fetion_password
    Base64.decode64(encrypted_fetion_password) if encrypted_fetion_password?
  end

  def password
    Base64.decode64(encrypted_password) if encrypted_password?
  end
  
  def decode_fetion_password!
    self.encrypted_fetion_password = Base64.decode64(encrypted_fetion_password)  if encrypted_fetion_password?
  end
  
  def fetion_changed?(args)
    mobile != args[:mobile] or fetion_password != args[:password]
  end
  
  def update_fetion!(args)
    self.mobile = args[:mobile]
    self.encrypted_fetion_password = args[:password]
    save(false)
  end
    
  def fetion?
    mobile?
  end
  
  def mobile?
    mobile.present? and fetion_version.lite? and lite_fetion_status.success?
  end
  
  def has_drawn_gift?(info)
    feed_of_gift(info).present?
  end
  
  def has_drawn_gifts
    Feed::MoneyGift.find_all_by_user_id(id,:order => 'created_at desc').each_with_object([]) do |feed,gifts|
      gift = feed.info
      gifts << gift
      def gift.current_user_feed=(feed)
        @feed = feed
      end 
      def gift.current_user_feed
        @feed
      end
      gift.current_user_feed = feed
    end
  end
  
  def hasnt_drawn_gifts
    Info.find_all_by_money_purpose('gift', :order => 'created_at desc').each_with_object([]) do |gift,gifts|
      gifts << gift if not has_drawn_gift?(gift)
    end
  end
  
  def feed_of_gift(info)
    Feed::MoneyGift.find_by_user_id_and_info_id(id,info.id)
  end
  
  def fetion_version
    ActiveSupport::StringInquirer.new(self[:fetion_version])
  end
  
  def lite_fetion_status
    ActiveSupport::StringInquirer.new(self[:lite_fetion_status])
  end
  
  def sex
    ActiveSupport::StringInquirer.new(self[:sex])
  end
  
  def lite_fetion_status!(status)
    self.lite_fetion_status = status
    save false
  end
  
  def lite_fetion_status!(status)
    self.lite_fetion_status = status
    save false
  end
  
  def admin?
    email == 'www.mytusi.com@gmail.com' or email == 'amon.lei@gmail.com' or nick_name == 'amon.lei' 
  end
  
  def add_sms_count!(args= {})
    args = {
       :sms_count => 1
    }.merge(args)
    self.sms_count += args[:sms_count]
    save(false)
  end
  
  def add_emails_count!(args= {})
    args = {
       :emails_count => 1
    }.merge(args)
    self.emails_count += args[:emails_count]
    save(false)
  end
  
  # :mobile
  # :password
  # :verifyImgId
  # :verifyCode
  def send_check_code_sm!(fetion_check_code, args = {})
    args[:content] = "麦吐司网的飞信手机绑定确认码：#{fetion_check_code}。请尽快确认，谢谢。【麦吐司网】"
    FetionSm.new(args).create!
  end
  
  def send_password_sm!    
    if fetion_version.lite?
      send_sm_by_lite_fetion! password_sm
    else
      FetionSm.new(
        :mobile => mobile,
        :password => fetion_password,
        :content => password_sm
      ).create!
    end
  end
  
  def login_at_now!
    update_attribute :login_at, Time.now
  end
  
  def authorized_code
    Digest::SHA1.hexdigest("#{id}_#{pk}_#{login_at}")
  end
  
  def authorized_code?(a_code)
    authorized_code == a_code
  end
  
  def high_star?
    star == 'high'
  end
  
  def low_star?
    star == 'low'
  end
  
  def inverse_star!
    self.star = high_star? ? 'low' : 'high'
    save(false)
  end
  
  def follow_hot_post_setting_by_hot_post_id(hot_post_id)
    FollowHotPostSetting.find_or_create_by_user_id_and_hot_post_id id, hot_post_id
  end

  def reset_user_tool_settings_count!
    User.reset_counters(id,:user_tool_settings)
  end
  
  def draw_money!
    if Date.today != money_drawn_on
      feed = Feed::MoneyDailyDraw.new(
        :user_id => id,
        :added_money => how_much_can_be_drawn,
        :money => money + how_much_can_be_drawn
      )
      self.money += how_much_can_be_drawn
      self.money_drawn_on == 1.days.ago.to_date ? (
        self.draw_money_duration_days += 1
      ) : (
        self.draw_money_duration_days = 1
      )
      self.money_drawn_on = Date.today
      save false
      feed.save!
    end
  end
  
  def custom_money!(how_much)
    logger.debug "========================="
    logger.debug "#{money} - #{how_much} = "    
    self.money -= how_much
    logger.debug "#{money}"
    yield
    save false
  end
  
  def has_drawn_money?
    Date.today == money_drawn_on
  end
  
  def the_lastest_drawn_money_feed
    Feed::MoneyDailyDraw.find_by_user_id(id,:order => 'id desc' )
  end
  
  def current_draw_money_duration_days
    if Date.today == money_drawn_on or 1.days.ago.to_date == money_drawn_on
      draw_money_duration_days
    else
      0
    end
  end
  
  def how_much_can_be_drawn
    if Date.today == money_drawn_on
      0
    else
      1.days.ago.to_date == money_drawn_on ? (
        draw_money_duration_days >= 7 ? ( 
          50
        ) : (
          (draw_money_duration_days + 1) * 5
        )
      ) : (
        5
      )
    end
  end
  
  def money_feeds(args = { :limit => 50})
    Feed.all(:conditions => ['user_id = ? and type like ? ',id,'Feed::Money%'], :order => 'id desc', :limit => args[:limit])
  end
  
  def tomorrow_draw_money_duration_days_if_drawn_today
    draw_money_duration_days + 1
  end
  
  def how_much_can_be_drawn_tomorrow_if_drawn_today
    if money_drawn_on.nil? 
      10
    elsif Date.today == money_drawn_on
      (draw_money_duration_days) >= 7 ? ( 
        50
      ) : (
        (draw_money_duration_days + 1) * 5
      )
    else
      1.days.ago.to_date == money_drawn_on ? (
        (draw_money_duration_days + 1) >= 7 ? ( 
          50
        ) : (
          (draw_money_duration_days + 2) * 5
        )
      ) : (
        10
      )
    end
  end
  
  def send_weather_alert_sm(info)
    Sm.create!( :user => self,
      :content => info.sm_content,
      :pri => 1)
  end
  
  def default_city
    UserToolSetting::WeatherForecast.find_by_user_id(id, :order => 'id asc').try(:area).try(:city)
  end
  
  def sex_feed
    Feed::MoneySex.find_by_user_id id
  end
  
  def try_to_create_sex_feed
    Feed::MoneySex.create(
      :user_id => id
    ) if (! sex.unknown?) and sex_feed.nil?
  end
    
  private
  # 加密密码
  def encode_password!
    self.encrypted_password = Base64.encode64(encrypted_password).chop
  end
  
  def encode_fetion_password!
    self.encrypted_fetion_password = Base64.encode64(encrypted_fetion_password).chop
  end

  def decode_password
    Base64.decode64(encrypted_password)
  end
  
  def password_sm
    "亲爱的#{nick_name}：您的麦吐司网登录密码是:#{password}.如果您持续收到这类的短信骚扰, 请尽快联络管理员(QQ:7861848).【麦吐司网】"
  end
  
end
